import axios from 'axios'
import qs from 'qs'
import { Message } from 'element-ui'

import config from './runtime'
import { globalErrorHandler } from './error-log'

interface HttpError {
  [key: number]: string
  [key: string]: string
}
const httpErrorMessage: HttpError = {
  400: 'Bad Request',
  401: 'Unauthorized',
  402: 'Payment Required',
  403: 'Forbidden',
  404: 'Not Found',
  405: 'Method Not Allowed',
  406: 'Not Acceptable',
  500: 'Internal Server Error',
  501: 'Not Implemented',
  502: 'Bad Gateway',
  503: 'Service Unavailable',
  504: 'Gateway Timeout',
  request_error: '发送请求时出现错误',
  no_respond: '服务器无响应',
  unknown_error: '未知错误'
}
const showHttpError = (errorCode: number | string): void => {
  Message({ message: httpErrorMessage[errorCode], type: 'error' })
}

const service = axios.create({
  baseURL: config.baseURL,
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
    'Content-Type': 'application/json; charset=utf-8'
  },
  paramsSerializer: params => qs.stringify(params, { skipNulls: true }),
  timeout: 6000,
  withCredentials: true
})

// Add a request interceptor
service.interceptors.request.use(
  config => {
    // Do something before request is sent
    return config
  },
  error => {
    // Do something with request error
    showHttpError('request_error')
    return Promise.reject(error)
  }
)

// Add a response interceptor
service.interceptors.response.use(
  response => {
    // Do something with response data
    return response
  },
  error => {
    // Do something with response error

    if (error.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx
      const status = error.response.status
      if (httpErrorMessage.hasOwnProperty(status)) {
        showHttpError(status)
      } else {
        showHttpError('unknown_error')
      }
    } else if (error.request) {
      // The request was made but no response was received
      // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
      // http.ClientRequest in node.js
      showHttpError('no_respond')
    } else {
      // Something happened in setting up the request that triggered an Error
    }
    globalErrorHandler(error)

    return Promise.reject(error)
  }
)

/* **************************************** */

export const $get = (url: string, params?: object) =>
  service({ url, method: 'get', params })

export const $delete = (url: string, params?: object) =>
  service({ url, method: 'delete', params })

export const $post = (url: string, data?: object, params?: object) =>
  service({ url, method: 'post', params, data })

export const $put = (url: string, data?: object, params?: object) =>
  service({ url, method: 'put', params, data })

export const $upload = (url: string, data?: object, params?: object) =>
  service({
    url,
    method: 'post',
    headers: { 'Content-Type': 'multipart/form-data' },
    params,
    data
  })

export const $simpleGet = (url: string, params?: object) =>
  service({ url, method: 'get', params, withCredentials: false })

export const $url = (url: string, params?: object): string => {
  let fullURL = ''
  let query = qs.stringify(params, { addQueryPrefix: true, skipNulls: true })
  if (/^(https?:)?\/\/\w+/.test(url)) {
    fullURL = url + query
  } else {
    fullURL = config.baseURL + url + query
  }
  return fullURL
}
